]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
Bug 591246 - Move towards shell-black02 mockup
authorColin Walters <walters@verbum.org>
Sun, 9 Aug 2009 23:48:54 +0000 (19:48 -0400)
committerColin Walters <walters@verbum.org>
Wed, 12 Aug 2009 20:07:05 +0000 (16:07 -0400)
Remove the last use of passing width into Dash by having the
Pane with the previews scaling dynamically and relying on
Clutter scaling.

If we only have one workspace, don't display a selection frame
for it.

Rework Dash into a searchArea and sectionArea, which get
explicitly sized by overlay.js.  We use the workspaces size
to choose the size of those dash areas.

Switch dash colors/boxes etc. to ones from shell-black02.

Add a gradient to the panel.

Add a magnifier.svg for use in search.

data/Makefile.am
data/magnifier.svg [new file with mode: 0644]
data/view-more-activated.svg [deleted file]
data/view-more.svg [deleted file]
js/ui/appDisplay.js
js/ui/dash.js
js/ui/docDisplay.js
js/ui/genericDisplay.js
js/ui/overview.js
js/ui/panel.js
js/ui/workspaces.js

index ca8d6dde06cb2fc8cdcb9183de1215b4019eace8..eee6b2d51ff60c6b4fe7d6acf7c59881ea69d101 100644 (file)
@@ -18,9 +18,8 @@ dist_image_DATA =             \
        add-workspace.svg       \
        close.svg               \
        info.svg                \
-       remove-workspace.svg    \
-       view-more-activated.svg \
-       view-more.svg
+       magnifier.svg  \
+       remove-workspace.svg
 
 schemadir  = @GCONF_SCHEMA_FILE_DIR@
 schema_DATA = gnome-shell.schemas
diff --git a/data/magnifier.svg b/data/magnifier.svg
new file mode 100644 (file)
index 0000000..836ee69
--- /dev/null
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Generator: Adobe Illustrator 13.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 14948)  -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   id="Foreground"
+   x="0px"
+   y="0px"
+   width="29px"
+   height="18px"
+   viewBox="0 0 29 18"
+   enable-background="new 0 0 29 18"
+   xml:space="preserve"
+   sodipodi:version="0.32"
+   inkscape:version="0.46+devel"
+   sodipodi:docname="magnifier.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape"><metadata
+   id="metadata16"><rdf:RDF><cc:Work
+       rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+         rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
+   id="defs14"><inkscape:perspective
+     sodipodi:type="inkscape:persp3d"
+     inkscape:vp_x="0 : 9 : 1"
+     inkscape:vp_y="0 : 1000 : 0"
+     inkscape:vp_z="29 : 9 : 1"
+     inkscape:persp3d-origin="14.5 : 6 : 1"
+     id="perspective18" /></defs><sodipodi:namedview
+   inkscape:window-height="728"
+   inkscape:window-width="1103"
+   inkscape:pageshadow="2"
+   inkscape:pageopacity="0"
+   guidetolerance="10.0"
+   gridtolerance="10.0"
+   objecttolerance="10.0"
+   borderopacity="1.0"
+   bordercolor="#666666"
+   pagecolor="#000000"
+   id="base"
+   showgrid="false"
+   inkscape:zoom="27.260185"
+   inkscape:cx="14.5"
+   inkscape:cy="9"
+   inkscape:window-x="142"
+   inkscape:window-y="25"
+   inkscape:current-layer="Foreground"><inkscape:grid
+     type="xygrid"
+     id="grid2391"
+     empspacing="5"
+     visible="true"
+     enabled="true"
+     snapvisiblegridlinesonly="true" /></sodipodi:namedview>
+
+<g
+   id="g5"
+   style="fill:#ffffff;fill-opacity:1">
+       <path
+   fill="#FFFFFF"
+   d="M6.246,13.98c-0.319-0.319-0.319-0.837,0-1.157l3.717-3.717c0.319-0.319,0.837-0.319,1.157,0l0.786,0.787   c0.32,0.319,0.32,0.837,0,1.157l-3.717,3.717c-0.32,0.319-0.838,0.319-1.157,0L6.246,13.98L6.246,13.98z"
+   id="path7"
+   style="fill:#ffffff;fill-opacity:1" />
+       <path
+   fill="#FFFFFF"
+   d="M9.076,11.937"
+   id="path9"
+   style="fill:#ffffff;fill-opacity:1" />
+</g>
+<path
+   fill-rule="evenodd"
+   clip-rule="evenodd"
+   fill="#FFFFFF"
+   d="M11.25,7.5c0-1.243,1.007-2.25,2.25-2.25s2.25,1.007,2.25,2.25  s-1.007,2.25-2.25,2.25S11.25,8.743,11.25,7.5z M9,7.5C9,5.015,11.015,3,13.5,3S18,5.015,18,7.5S15.985,12,13.5,12S9,9.985,9,7.5z"
+   id="path11"
+   style="fill:#ffffff;fill-opacity:1" />
+</svg>
\ No newline at end of file
diff --git a/data/view-more-activated.svg b/data/view-more-activated.svg
deleted file mode 100644 (file)
index 787b1ad..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Generator: Adobe Illustrator 13.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 14948)  -->
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   version="1.1"
-   id="Foreground"
-   x="0px"
-   y="0px"
-   width="29px"
-   height="18px"
-   viewBox="0 0 29 18"
-   enable-background="new 0 0 29 18"
-   xml:space="preserve"
-   sodipodi:version="0.32"
-   inkscape:version="0.46"
-   sodipodi:docname="search_2.svg"
-   inkscape:output_extension="org.inkscape.output.svg.inkscape"><metadata
-   id="metadata16"><rdf:RDF><cc:Work
-       rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
-         rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
-   id="defs14"><inkscape:perspective
-   sodipodi:type="inkscape:persp3d"
-   inkscape:vp_x="0 : 9 : 1"
-   inkscape:vp_y="0 : 1000 : 0"
-   inkscape:vp_z="29 : 9 : 1"
-   inkscape:persp3d-origin="14.5 : 6 : 1"
-   id="perspective18" />
-       
-       
-</defs><sodipodi:namedview
-   inkscape:window-height="728"
-   inkscape:window-width="1103"
-   inkscape:pageshadow="2"
-   inkscape:pageopacity="0.0"
-   guidetolerance="10.0"
-   gridtolerance="10.0"
-   objecttolerance="10.0"
-   borderopacity="1.0"
-   bordercolor="#666666"
-   pagecolor="#ffffff"
-   id="base"
-   showgrid="false"
-   inkscape:zoom="19.275862"
-   inkscape:cx="14.5"
-   inkscape:cy="9"
-   inkscape:window-x="40"
-   inkscape:window-y="40"
-   inkscape:current-layer="Foreground"><inkscape:grid
-     type="xygrid"
-     id="grid2391" /></sodipodi:namedview>
-
-<path
-   style="fill:#4669a9;fill-opacity:1"
-   id="path9"
-   d="" />
-<path
-   id="path3"
-   style="fill:#3d5a93;fill-opacity:1"
-   d="M 0,3 C 0,1.343 1.343,0 3,0 L 20,0 C 20.515,0 21.027,0.195 21.42,0.588 L 28.412,7.58 C 29.196,8.364 29.196,9.636 28.412,10.42 L 21.42,17.412 C 21.028,17.804 20.514,18 20,18 L 3,18 C 1.343,18 0,16.657 0,15 L 0,3 zM 13.5,3 C 11.015,3 9,5.015 9,7.5 C 9,8.2423219 9.1815696,8.9452421 9.5,9.5625 L 6.25,12.8125 C 5.931,13.1325 5.9310002,13.64975 6.25,13.96875 L 7.03125,14.78125 C 7.35025,15.10025 7.8674999,15.10025 8.1875,14.78125 L 11.46875,11.5 C 12.080227,11.810879 12.767137,12 13.5,12 C 15.985,12 18,9.985 18,7.5 C 18,5.015 15.985,3 13.5,3 z M 11.25,7.5 C 11.25,6.257 12.257,5.25 13.5,5.25 C 14.743,5.25 15.75,6.257 15.75,7.5 C 15.75,8.743 14.743,9.75 13.5,9.75 C 12.257,9.75 11.25,8.743 11.25,7.5 z" />
-</svg>
\ No newline at end of file
diff --git a/data/view-more.svg b/data/view-more.svg
deleted file mode 100644 (file)
index 31af4ee..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Generator: Adobe Illustrator 13.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 14948)  -->
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   version="1.1"
-   id="Foreground"
-   x="0px"
-   y="0px"
-   width="29px"
-   height="18px"
-   viewBox="0 0 29 18"
-   enable-background="new 0 0 29 18"
-   xml:space="preserve"
-   sodipodi:version="0.32"
-   inkscape:version="0.46"
-   sodipodi:docname="search_1.svg"
-   inkscape:output_extension="org.inkscape.output.svg.inkscape"><metadata
-   id="metadata16"><rdf:RDF><cc:Work
-       rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
-         rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
-   id="defs14"><inkscape:perspective
-     sodipodi:type="inkscape:persp3d"
-     inkscape:vp_x="0 : 9 : 1"
-     inkscape:vp_y="0 : 1000 : 0"
-     inkscape:vp_z="29 : 9 : 1"
-     inkscape:persp3d-origin="14.5 : 6 : 1"
-     id="perspective18" /></defs><sodipodi:namedview
-   inkscape:window-height="728"
-   inkscape:window-width="1103"
-   inkscape:pageshadow="2"
-   inkscape:pageopacity="0.0"
-   guidetolerance="10.0"
-   gridtolerance="10.0"
-   objecttolerance="10.0"
-   borderopacity="1.0"
-   bordercolor="#666666"
-   pagecolor="#ffffff"
-   id="base"
-   showgrid="false"
-   inkscape:zoom="19.275862"
-   inkscape:cx="14.5"
-   inkscape:cy="9"
-   inkscape:window-x="40"
-   inkscape:window-y="40"
-   inkscape:current-layer="Foreground"><inkscape:grid
-     type="xygrid"
-     id="grid2391" /></sodipodi:namedview>
-<path
-   d="M0,3c0-1.657,1.343-3,3-3h17c0.515,0,1.027,0.195,1.42,0.588l6.992,6.992c0.784,0.784,0.784,2.056,0,2.84l-6.992,6.992  C21.028,17.804,20.514,18,20,18H3c-1.657,0-3-1.343-3-3V3z"
-   id="path3"
-   style="fill:#151e2f;fill-opacity:1" />
-<g
-   id="g5"
-   style="fill:#4669a9;fill-opacity:1">
-       <path
-   fill="#FFFFFF"
-   d="M6.246,13.98c-0.319-0.319-0.319-0.837,0-1.157l3.717-3.717c0.319-0.319,0.837-0.319,1.157,0l0.786,0.787   c0.32,0.319,0.32,0.837,0,1.157l-3.717,3.717c-0.32,0.319-0.838,0.319-1.157,0L6.246,13.98L6.246,13.98z"
-   id="path7"
-   style="fill:#4669a9;fill-opacity:1" />
-       <path
-   fill="#FFFFFF"
-   d="M9.076,11.937"
-   id="path9"
-   style="fill:#4669a9;fill-opacity:1" />
-</g>
-<path
-   fill-rule="evenodd"
-   clip-rule="evenodd"
-   fill="#FFFFFF"
-   d="M11.25,7.5c0-1.243,1.007-2.25,2.25-2.25s2.25,1.007,2.25,2.25  s-1.007,2.25-2.25,2.25S11.25,8.743,11.25,7.5z M9,7.5C9,5.015,11.015,3,13.5,3S18,5.015,18,7.5S15.985,12,13.5,12S9,9.985,9,7.5z"
-   id="path11"
-   style="fill:#4669a9;fill-opacity:1" />
-</svg>
\ No newline at end of file
index a1e5f6f7ad6b9c2b51eb731af616c4953e07e8aa..7d28fbaff0e210acc4b65e82a873a5a714e6968c 100644 (file)
@@ -565,9 +565,7 @@ WellGrid.prototype = {
     _init: function() {
         this.actor = new Shell.GenericContainer();
 
-        this._separator = new Big.Box({ border_color: GenericDisplay.ITEM_DISPLAY_NAME_COLOR,
-                                        border_top: 1,
-                                        height: 1 });
+        this._separator = new Big.Box({ height: 1 });
         this.actor.add_actor(this._separator);
         this._separatorIndex = 0;
         this._cachedSeparatorY = 0;
index c5d8030a6c1777762a5b48bcad27192e88adc71b..59426d5e0a0b3c63e9dc5373b5667c21eb48c9ee 100644 (file)
@@ -5,6 +5,7 @@ const Clutter = imports.gi.Clutter;
 const Gio = imports.gi.Gio;
 const Gtk = imports.gi.Gtk;
 const Mainloop = imports.mainloop;
+const Pango = imports.gi.Pango;
 const Shell = imports.gi.Shell;
 const Signals = imports.signals;
 const Lang = imports.lang;
@@ -18,14 +19,35 @@ const Main = imports.ui.main;
 
 const DEFAULT_PADDING = 4;
 const DASH_SECTION_PADDING = 6;
-const DASH_SECTION_SPACING = 12;
+const DASH_SECTION_SPACING = 40;
 const DASH_CORNER_RADIUS = 5;
-const DASH_SEARCH_BG_COLOR = new Clutter.Color();
-DASH_SEARCH_BG_COLOR.from_pixel(0xffffffff);
-const DASH_SECTION_COLOR = new Clutter.Color();
-DASH_SECTION_COLOR.from_pixel(0x846c3dff);
-const DASH_TEXT_COLOR = new Clutter.Color();
-DASH_TEXT_COLOR.from_pixel(0xffffffff);
+
+const BACKGROUND_COLOR = new Clutter.Color();
+BACKGROUND_COLOR.from_pixel(0x000000c0);
+
+const DASH_PADDING_SIDE = 14;
+
+const SEARCH_BORDER_BOTTOM_COLOR = new Clutter.Color();
+SEARCH_BORDER_BOTTOM_COLOR.from_pixel(0x191919ff);
+
+const SECTION_BORDER_COLOR = new Clutter.Color();
+SECTION_BORDER_COLOR.from_pixel(0x262626ff);
+const SECTION_BORDER = 1;
+const SECTION_INNER_BORDER_COLOR = new Clutter.Color();
+SECTION_INNER_BORDER_COLOR.from_pixel(0x000000ff);
+const SECTION_BACKGROUND_TOP_COLOR = new Clutter.Color();
+SECTION_BACKGROUND_TOP_COLOR.from_pixel(0x161616ff);
+const SECTION_BACKGROUND_BOTTOM_COLOR = new Clutter.Color();
+SECTION_BACKGROUND_BOTTOM_COLOR.from_pixel(0x000000ff);
+const SECTION_INNER_SPACING = 8;
+
+const BROWSE_ACTIVATED_BG = new Clutter.Color();
+BROWSE_ACTIVATED_BG.from_pixel(0x303030f0);
+
+const TEXT_COLOR = new Clutter.Color();
+TEXT_COLOR.from_pixel(0x5f5f5fff);
+const BRIGHT_TEXT_COLOR = new Clutter.Color();
+BRIGHT_TEXT_COLOR.from_pixel(0xffffffff);
 
 const PANE_BORDER_COLOR = new Clutter.Color();
 PANE_BORDER_COLOR.from_pixel(0x101d3cfa);
@@ -144,7 +166,7 @@ ResultArea.prototype = {
 // Utility function shared between ResultPane and the DocDisplay in the main dash.
 // Connects to the detail signal of the display, and on-demand creates a new
 // pane.
-function createPaneForDetails(dash, display, detailsWidth) {
+function createPaneForDetails(dash, display) {
     let detailPane = null;
     display.connect('show-details', Lang.bind(this, function(display, index) {
         if (detailPane == null) {
@@ -160,7 +182,7 @@ function createPaneForDetails(dash, display, detailsWidth) {
 
         if (index >= 0) {
             detailPane.destroyContent();
-            let details = display.createDetailsForIndex(index, detailsWidth, -1);
+            let details = display.createDetailsForIndex(index, -1);
             detailPane.content.append(details, Big.BoxPackFlags.EXPAND);
             detailPane.open();
         } else {
@@ -170,17 +192,16 @@ function createPaneForDetails(dash, display, detailsWidth) {
     return null;
 }
 
-function ResultPane(dash, detailsWidth) {
-    this._init(dash, detailsWidth);
+function ResultPane(dash) {
+    this._init(dash);
 }
 
 ResultPane.prototype = {
     __proto__: Pane.prototype,
 
-    _init: function(dash, detailsWidth) {
+    _init: function(dash) {
         Pane.prototype._init.call(this);
         this._dash = dash;
-        this._detailsWidth = detailsWidth;
     },
 
     // Create an instance of displayClass and pack it into this pane's
@@ -188,7 +209,7 @@ ResultPane.prototype = {
     packResults: function(displayClass, enableNavigation) {
         let resultArea = new ResultArea(displayClass, enableNavigation);
 
-        createPaneForDetails(this._dash, resultArea.display, this._detailsWidth);
+        createPaneForDetails(this._dash, resultArea.display);
 
         this.content.append(resultArea.actor, Big.BoxPackFlags.EXPAND);
         this.connect('open-state-changed', Lang.bind(this, function(pane, isOpen) {
@@ -206,31 +227,89 @@ SearchEntry.prototype = {
     _init : function() {
         this.actor = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
                                    y_align: Big.BoxAlignment.CENTER,
-                                   background_color: DASH_SEARCH_BG_COLOR,
-                                   corner_radius: 4,
-                                   spacing: DEFAULT_PADDING,
-                                   padding: DEFAULT_PADDING
-                                 });
-
-        let icon = new Gio.ThemedIcon({ name: 'gtk-find' });
-        let searchIconTexture = Shell.TextureCache.get_default().load_gicon(icon, 16);
-        this.actor.append(searchIconTexture, Big.BoxPackFlags.NONE);
-
+                                   border_bottom: SECTION_BORDER,
+                                   border_color: SEARCH_BORDER_BOTTOM_COLOR });
         this.pane = null;
 
+        this._defaultText = "Find apps or documents";
+
+        let textProperties = { font_name: "Sans 12" };
+        let entryProperties = { editable: true,
+                                activatable: true,
+                                single_line_mode: true,
+                                color: BRIGHT_TEXT_COLOR,
+                                cursor_color: BRIGHT_TEXT_COLOR,
+                                text: '' };
+        Lang.copyProperties(textProperties, entryProperties);
         // We need to initialize the text for the entry to have the cursor displayed
         // in it. See http://bugzilla.openedhand.com/show_bug.cgi?id=1365
-        this.entry = new Clutter.Text({ font_name: "Sans 14px",
-                                        editable: true,
-                                        activatable: true,
-                                        singleLineMode: true,
-                                        text: ""
-                                      });
+        this.entry = new Clutter.Text(entryProperties);
+        this.entry.connect('notify::text', Lang.bind(this, function () {
+            this._resetTextState();
+        }));
         this.actor.append(this.entry, Big.BoxPackFlags.EXPAND);
+
+        // Mark as editable just to get a cursor
+        let defaultTextProperties = { ellipsize: Pango.EllipsizeMode.END,
+                                      text: "Find apps or documents",
+                                      editable: true,
+                                      color: TEXT_COLOR,
+                                      cursor_visible: false,
+                                      single_line_mode: true };
+        Lang.copyProperties(textProperties, defaultTextProperties);
+        this._defaultText = new Clutter.Text(defaultTextProperties);
+        this.actor.add_actor(this._defaultText);
+        this.entry.connect('notify::allocation', Lang.bind(this, function () {
+            this._repositionDefaultText();
+        }));
+
+        this._iconBox = new Big.Box({ x_align: Big.BoxAlignment.CENTER,
+                                      y_align: Big.BoxAlignment.CENTER });
+        this.actor.append(this._iconBox, Big.BoxPackFlags.END);
+
+        let global = Shell.Global.get();
+        let magnifierUri = "file://" + global.imagedir + "magnifier.svg";
+        this._magnifierIcon = Shell.TextureCache.get_default().load_uri_sync(Shell.TextureCachePolicy.FOREVER,
+                                                                             magnifierUri, 29, 18);
+        let closeUri = "file://" + global.imagedir + "close.svg";
+        this._closeIcon = Shell.TextureCache.get_default().load_uri_sync(Shell.TextureCachePolicy.FOREVER,
+                                                                         closeUri, 18, 18);
+        this._closeIcon.reactive = true;
+        this._closeIcon.connect('button-press-event', Lang.bind(this, function () {
+            this.entry.text = '';
+        }));
+        this._repositionDefaultText();
+        this._resetTextState();
     },
 
     setPane: function (pane) {
         this._pane = pane;
+    },
+
+    reset: function () {
+        this.entry.text = '';
+    },
+
+    getText: function () {
+        return this.entry.text;
+    },
+
+    _resetTextState: function () {
+        let text = this.getText();
+        this._iconBox.remove_all();
+        if (text != '') {
+            this._defaultText.hide();
+            this._iconBox.append(this._closeIcon, Big.BoxPackFlags.NONE);
+        } else {
+            this._defaultText.show();
+            this._iconBox.append(this._magnifierIcon, Big.BoxPackFlags.NONE);
+        }
+    },
+
+    _repositionDefaultText: function () {
+        // Offset a little to show the cursor
+        this._defaultText.set_position(this.entry.x + 4, this.entry.y);
+        this._defaultText.set_size(this.entry.width, this.entry.height);
     }
 };
 Signals.addSignalMethods(SearchEntry.prototype);
@@ -242,22 +321,21 @@ function MoreLink() {
 MoreLink.prototype = {
     _init : function () {
         this.actor = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
+                                   padding_right: DEFAULT_PADDING,
                                    padding_left: DEFAULT_PADDING,
-                                   padding_right: DEFAULT_PADDING });
-        let global = Shell.Global.get();
-        let inactiveUri = "file://" + global.imagedir + "view-more.svg";
-        let activeUri = "file://" + global.imagedir + "view-more-activated.svg";
-        this._inactiveIcon = Shell.TextureCache.get_default().load_uri_sync(Shell.TextureCachePolicy.FOREVER,
-                                                                            inactiveUri, 29, 18);
-        this._activeIcon = Shell.TextureCache.get_default().load_uri_sync(Shell.TextureCachePolicy.FOREVER,
-                                                                          activeUri, 29, 18);
-        this._iconBox = new Big.Box({ reactive: true });
-        this._iconBox.append(this._inactiveIcon, Big.BoxPackFlags.NONE);
-        this.actor.append(this._iconBox, Big.BoxPackFlags.END);
-
+                                   reactive: true,
+                                   x_align: Big.BoxAlignment.CENTER,
+                                   y_align: Big.BoxAlignment.CENTER,
+                                   border_left: SECTION_BORDER,
+                                   border_color: SECTION_BORDER_COLOR });
         this.pane = null;
 
-        this._iconBox.connect('button-press-event', Lang.bind(this, function (b, e) {
+        let text = new Clutter.Text({ font_name: "Sans 12px",
+                                      color: BRIGHT_TEXT_COLOR,
+                                      text: "Browse" });
+        this.actor.append(text, Big.BoxPackFlags.NONE);
+
+        this.actor.connect('button-press-event', Lang.bind(this, function (b, e) {
             if (this.pane == null) {
                 // Ensure the pane is created; the activated handler will call setPane
                 this.emit('activated');
@@ -270,41 +348,66 @@ MoreLink.prototype = {
     setPane: function (pane) {
         this._pane = pane;
         this._pane.connect('open-state-changed', Lang.bind(this, function(pane, isOpen) {
-            this._iconBox.remove_all();
-            this._iconBox.append(isOpen ? this._activeIcon : this._inactiveIcon,
-                                 Big.BoxPackFlags.NONE);
         }));
     }
 }
 
 Signals.addSignalMethods(MoreLink.prototype);
 
-function SectionHeader(title) {
-    this._init(title);
+function SectionHeader(title, suppressBrowse) {
+    this._init(title, suppressBrowse);
 }
 
 SectionHeader.prototype = {
-    _init : function (title) {
-        this.actor = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL });
-        let text = new Clutter.Text({ color: DASH_SECTION_COLOR,
-                                      font_name: "Sans Bold 10px",
+    _init : function (title, suppressBrowse) {
+        this.actor = new Big.Box({ border: SECTION_BORDER,
+                                   border_color: SECTION_BORDER_COLOR });
+        this._innerBox = new Big.Box({ border: SECTION_BORDER,
+                                       border_color: SECTION_INNER_BORDER_COLOR,
+                                       padding_left: DEFAULT_PADDING,
+                                       orientation: Big.BoxOrientation.HORIZONTAL });
+        this.actor.append(this._innerBox, Big.BoxPackFlags.EXPAND);
+        let backgroundGradient = Shell.create_vertical_gradient(SECTION_BACKGROUND_TOP_COLOR,
+                                                                SECTION_BACKGROUND_BOTTOM_COLOR);
+        this._innerBox.add_actor(backgroundGradient);
+        this._innerBox.connect('notify::allocation', Lang.bind(this, function (actor) {
+            let [width, height] = actor.get_size();
+            backgroundGradient.set_size(width, height);
+        }));
+        let textBox = new Big.Box({ padding_top: DEFAULT_PADDING,
+                                    padding_bottom: DEFAULT_PADDING });
+        let text = new Clutter.Text({ color: TEXT_COLOR,
+                                      font_name: "Sans Bold 12px",
                                       text: title });
-        this.moreLink = new MoreLink();
-        this.actor.append(text, Big.BoxPackFlags.EXPAND);
-        this.actor.append(this.moreLink.actor, Big.BoxPackFlags.END);
+        textBox.append(text, Big.BoxPackFlags.NONE);
+        this._innerBox.append(textBox, Big.BoxPackFlags.EXPAND);
+        if (!suppressBrowse) {
+            this.moreLink = new MoreLink();
+            this._innerBox.append(this.moreLink.actor, Big.BoxPackFlags.END);
+        }
     }
 }
 
-function Dash(displayGridColumnWidth) {
-    this._init(displayGridColumnWidth);
+function Section(titleString, suppressBrowse) {
+    this._init(titleString, suppressBrowse);
 }
 
-Dash.prototype = {
-    _init : function(displayGridColumnWidth) {
-        this._width = displayGridColumnWidth;
+Section.prototype = {
+    _init: function(titleString, suppressBrowse) {
+        this.actor = new Big.Box({ spacing: SECTION_INNER_SPACING });
+        this.header = new SectionHeader(titleString, suppressBrowse);
+        this.actor.append(this.header.actor, Big.BoxPackFlags.NONE);
+        this.content = new Big.Box();
+        this.actor.append(this.content, Big.BoxPackFlags.EXPAND);
+    }
+}
 
-        this._detailsWidth = displayGridColumnWidth * 2;
+function Dash() {
+    this._init();
+}
 
+Dash.prototype = {
+    _init : function() {
         let global = Shell.Global.get();
 
         // dash and the popup panes need to be reactive so that the clicks in unoccupied places on them
@@ -316,14 +419,21 @@ Dash.prototype = {
         // of the Group actor ends up including the width of its hidden children, so we were getting a reactive object as
         // wide as the details pane that was blocking the clicks to the workspaces underneath it even when the details pane
         // was actually hidden.
-        this.actor = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
-                                   width: this._width,
-                                   padding: DEFAULT_PADDING,
+        this.actor = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
+                                   background_color: BACKGROUND_COLOR,
+                                   corner_radius: DASH_CORNER_RADIUS,
+                                   padding_left: DASH_PADDING_SIDE,
+                                   padding_right: DASH_PADDING_SIDE,
                                    reactive: true });
 
-        this.dashContainer = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
-                                           spacing: DASH_SECTION_SPACING });
-        this.actor.append(this.dashContainer, Big.BoxPackFlags.EXPAND);
+        // Size for this one explicitly set from overlay.js
+        this.searchArea = new Big.Box({ y_align: Big.BoxAlignment.CENTER });
+
+        this.sectionArea = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
+                                         spacing: DASH_SECTION_SPACING });
+
+        this.actor.append(this.searchArea, Big.BoxPackFlags.NONE);
+        this.actor.append(this.sectionArea, Big.BoxPackFlags.NONE);
 
         // The currently active popup display
         this._activePane = null;
@@ -333,24 +443,25 @@ Dash.prototype = {
         this._searchPane = null;
         this._searchActive = false;
         this._searchEntry = new SearchEntry();
-        this.dashContainer.append(this._searchEntry.actor, Big.BoxPackFlags.NONE);
+        this.searchArea.append(this._searchEntry.actor, Big.BoxPackFlags.EXPAND);
 
         this._searchAreaApps = null;
         this._searchAreaDocs = null;
 
         this._searchQueued = false;
         this._searchEntry.entry.connect('text-changed', Lang.bind(this, function (se, prop) {
-            this._searchActive = this._searchEntry.text != '';
+            let text = this._searchEntry.getText();
+            this._searchActive = text != '';
             if (this._searchQueued)
                 return;
             if (this._searchPane == null) {
-                this._searchPane = new ResultPane(this, this._detailsWidth);
-                this._searchPane.content.append(new Clutter.Text({ color: DASH_SECTION_COLOR,
+                this._searchPane = new ResultPane(this);
+                this._searchPane.content.append(new Clutter.Text({ color: TEXT_COLOR,
                                                                    font_name: 'Sans Bold 10px',
                                                                    text: "APPLICATIONS" }),
                                                  Big.BoxPackFlags.NONE);
                 this._searchAreaApps = this._searchPane.packResults(AppDisplay.AppDisplay, false);
-                this._searchPane.content.append(new Clutter.Text({ color: DASH_SECTION_COLOR,
+                this._searchPane.content.append(new Clutter.Text({ color: TEXT_COLOR,
                                                                    font_name: 'Sans Bold 10px',
                                                                    text: "RECENT DOCUMENTS" }),
                                                  Big.BoxPackFlags.NONE);
@@ -360,8 +471,9 @@ Dash.prototype = {
             }
             this._searchQueued = true;
             Mainloop.timeout_add(250, Lang.bind(this, function() {
+                let text = this._searchEntry.getText();
                 // Strip leading and trailing whitespace
-                let text = this._searchEntry.entry.text.replace(/^\s+/g, "").replace(/\s+$/g, "");
+                text = text.replace(/^\s+/g, "").replace(/\s+$/g, "");
                 this._searchQueued = false;
                 this._searchAreaApps.setSearch(text);
                 this._searchAreaDocs.setSearch(text);
@@ -380,12 +492,13 @@ Dash.prototype = {
             return true;
         }));
         this._searchEntry.entry.connect('key-press-event', Lang.bind(this, function (se, e) {
+            let text = this._searchEntry.getText();
             let symbol = Shell.get_event_key_symbol(e);
             if (symbol == Clutter.Escape) {
                 // Escape will keep clearing things back to the desktop. First, if
                 // we have active text, we remove it.
-                if (this._searchEntry.entry.text != '')
-                    this._searchEntry.entry.text = '';
+                if (text != '')
+                    this._searchEntry.reset();
                 // Next, if we're in one of the "more" modes or showing the details pane, close them
                 else if (this._activePane != null)
                     this._activePane.close();
@@ -423,64 +536,49 @@ Dash.prototype = {
 
         /***** Applications *****/
 
-        let appsHeader = new SectionHeader("APPLICATIONS");
-        this._appsSection = new Big.Box({ spacing: DEFAULT_PADDING });
-        this._appsSection.append(appsHeader.actor, Big.BoxPackFlags.NONE);
-
-        this._appsContent = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL });
-        this._appsSection.append(this._appsContent, Big.BoxPackFlags.EXPAND);
-        this._appWell = new AppDisplay.AppWell();
-        this._appsContent.append(this._appWell.actor, Big.BoxPackFlags.EXPAND);
+        let appsSection = new Section("APPLICATIONS");
+        let appWell = new AppDisplay.AppWell();
+        appsSection.content.append(appWell.actor, Big.BoxPackFlags.EXPAND);
 
         this._moreAppsPane = null;
-        appsHeader.moreLink.connect('activated', Lang.bind(this, function (link) {
+        appsSection.header.moreLink.connect('activated', Lang.bind(this, function (link) {
             if (this._moreAppsPane == null) {
-                this._moreAppsPane = new ResultPane(this, this._detailsWidth);
+                this._moreAppsPane = new ResultPane(this);
                 this._moreAppsPane.packResults(AppDisplay.AppDisplay, true);
                 this._addPane(this._moreAppsPane);
                 link.setPane(this._moreAppsPane);
            }
         }));
 
-        this.dashContainer.append(this._appsSection, Big.BoxPackFlags.NONE);
+        this.sectionArea.append(appsSection.actor, Big.BoxPackFlags.NONE);
 
         /***** Places *****/
 
-        let placesSection = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
-                                          spacing: DEFAULT_PADDING });
-        let placesHeader = new SectionHeader("PLACES");
-        placesSection.append(placesHeader.actor, Big.BoxPackFlags.NONE);
-
+        let placesSection = new Section("PLACES", true);
         let placesDisplay = new Places.Places();
-        placesSection.append(placesDisplay.actor, Big.BoxPackFlags.EXPAND);
-
-        this.dashContainer.append(placesSection, Big.BoxPackFlags.NONE);
+        placesSection.content.append(placesDisplay.actor, Big.BoxPackFlags.EXPAND);
+        this.sectionArea.append(placesSection.actor, Big.BoxPackFlags.NONE);
 
         /***** Documents *****/
 
-        this._docsSection = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
-                                          spacing: DEFAULT_PADDING });
-        this._moreDocsPane = null;
-
-        let docsHeader = new SectionHeader("RECENT DOCUMENTS");
-        this._docsSection.append(docsHeader.actor, Big.BoxPackFlags.NONE);
-
-        this._docDisplay = new DocDisplay.DocDisplay();
-        this._docDisplay.load();
-        this._docsSection.append(this._docDisplay.actor, Big.BoxPackFlags.EXPAND);
+        let docsSection = new Section("RECENT DOCUMENTS");
 
-        createPaneForDetails(this, this._docDisplay, this._detailsWidth);
+        let docDisplay = new DocDisplay.DocDisplay();
+        docDisplay.load();
+        docsSection.content.append(docDisplay.actor, Big.BoxPackFlags.EXPAND);
+        createPaneForDetails(this, docDisplay);
 
-        docsHeader.moreLink.connect('activated', Lang.bind(this, function (link) {
+        this._moreDocsPane = null;
+        docsSection.header.moreLink.connect('activated', Lang.bind(this, function (link) {
             if (this._moreDocsPane == null) {
-                this._moreDocsPane = new ResultPane(this, this._detailsWidth);
+                this._moreDocsPane = new ResultPane(this);
                 this._moreDocsPane.packResults(DocDisplay.DocDisplay, true);
                 this._addPane(this._moreDocsPane);
                 link.setPane(this._moreDocsPane);
            }
         }));
 
-        this.dashContainer.append(this._docsSection, Big.BoxPackFlags.EXPAND);
+        this.sectionArea.append(docsSection.actor, Big.BoxPackFlags.EXPAND);
     },
 
     show: function() {
@@ -489,9 +587,8 @@ Dash.prototype = {
     },
 
     hide: function() {
-        this._firstSelectAfterOverviewShow = true;
-        if (this._searchEntry.entry.text != '')
-            this._searchEntry.entry.text = '';
+        this._firstSelectAfterOverlayShow = true;
+        this._searchEntry.reset();
         if (this._activePane != null)
             this._activePane.close();
     },
index d2d4fa305de4b539d650277a3f5a0055a2658e43..8dd133966625a3aad872d4e6f2d9b58d21cd5bec 100644 (file)
@@ -68,13 +68,13 @@ DocDisplayItem.prototype = {
 
     // Creates and returns a large preview icon, but only if this._docInfo is an image file
     // and we were able to generate a pixbuf from it successfully.
-    _createLargePreviewIcon : function(availableWidth, availableHeight) {
+    _createLargePreviewIcon : function() {
         if (this._docInfo.mimeType == null || this._docInfo.mimeType.indexOf("image/") != 0)
             return null;
 
         try {
             return Shell.TextureCache.get_default().load_uri_sync(Shell.TextureCachePolicy.NONE,
-                                                                  this._docInfo.uri, availableWidth, availableHeight);
+                                                                  this._docInfo.uri, -1, -1);
         } catch (e) {
             // An exception will be raised when the image format isn't know
             /* FIXME: http://bugzilla.gnome.org/show_bug.cgi?id=591480: should
index 3dbc4e92f264cc7203f3bb52d6cf248b0701ff7e..6f1347791e8ef3c34ce8afa7843a76b16e927796 100644 (file)
@@ -183,18 +183,14 @@ GenericDisplayItem.prototype = {
     /*
      * Returns an actor containing item details. In the future details can have more information than what
      * the preview pop-up has and be item-type specific.
-     *
-     * availableWidth - width available for displaying details
      */
-    createDetailsActor: function(availableWidth) {
+    createDetailsActor: function() {
 
         let details = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
-                                    spacing: PREVIEW_BOX_SPACING,
-                                    width: availableWidth });
+                                    spacing: PREVIEW_BOX_SPACING });
 
         let mainDetails = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
-                                        spacing: PREVIEW_BOX_SPACING,
-                                        width: availableWidth });
+                                        spacing: PREVIEW_BOX_SPACING });
 
         // Inner box with name and description
         let textDetails = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
@@ -216,7 +212,7 @@ GenericDisplayItem.prototype = {
         mainDetails.append(textDetails, Big.BoxPackFlags.EXPAND);
 
         let previewIcon = this._createPreviewIcon();
-        let largePreviewIcon = this._createLargePreviewIcon(availableWidth, -1);
+        let largePreviewIcon = this._createLargePreviewIcon();
 
         if (previewIcon != null && largePreviewIcon == null) {
             mainDetails.prepend(previewIcon, Big.BoxPackFlags.NONE);
@@ -303,7 +299,7 @@ GenericDisplayItem.prototype = {
     //// Virtual protected methods ////
 
     // Creates and returns a large preview icon, but only if we have a detailed image.
-    _createLargePreviewIcon : function(availableWidth, availableHeight) {
+    _createLargePreviewIcon : function() {
         return null;
     },
 
@@ -465,9 +461,9 @@ GenericDisplay.prototype = {
         return null;
     },
 
-    createDetailsForIndex: function(index, width, height) {
+    createDetailsForIndex: function(index) {
         let item = this._findDisplayedByIndex(index);
-        return item.createDetailsActor(width, height);
+        return item.createDetailsActor();
     },
 
     //// Protected methods ////
index 9d42ed159d6f6e98027a9d1dc5af17d5be954263..94b4cbdc4f04823bc5154f7d875838356a87b160 100644 (file)
@@ -109,7 +109,7 @@ Overview.prototype = {
         global.overlay_group.add_actor(this._group);
 
         // TODO - recalculate everything when desktop size changes
-        this._dash = new Dash.Dash(displayGridColumnWidth);
+        this._dash = new Dash.Dash();
         this._group.add_actor(this._dash.actor);
 
         // Container to hold popup pane chrome.
@@ -149,10 +149,34 @@ Overview.prototype = {
     relayout: function () {
         let global = Shell.Global.get();
 
-        let contentHeight = global.screen_height - Panel.PANEL_HEIGHT;
+        let screenHeight = global.screen_height;
+        let screenWidth = global.screen_width;
+
+        let contentHeight = screenHeight - Panel.PANEL_HEIGHT;
+
+        let workspaceColumnsUsed = wideScreen ? COLUMNS_FOR_WORKSPACES_WIDE_SCREEN : COLUMNS_FOR_WORKSPACES_REGULAR_SCREEN;
+        let workspaceRowsUsed = wideScreen ? ROWS_FOR_WORKSPACES_WIDE_SCREEN : ROWS_FOR_WORKSPACES_REGULAR_SCREEN;
+
+        this._workspacesWidth = displayGridColumnWidth * workspaceColumnsUsed
+                                  - WORKSPACE_GRID_PADDING * 2;
+        // We scale the vertical padding by (screenHeight / screenWidth)
+        // so that the workspace preserves its aspect ratio.
+        this._workspacesHeight = displayGridRowHeight * workspaceRowsUsed
+                                   - WORKSPACE_GRID_PADDING * (screenHeight / screenWidth) * 2;
 
-        this._dash.actor.set_position(0, Panel.PANEL_HEIGHT);
-        this._dash.actor.set_size(displayGridColumnWidth, contentHeight);
+        this._workspacesX = displayGridColumnWidth + WORKSPACE_GRID_PADDING;
+        this._workspacesY = displayGridRowHeight + WORKSPACE_GRID_PADDING * (screenHeight / screenWidth);
+
+        let dashY = Panel.PANEL_HEIGHT;
+        this._dash.actor.set_position(0, dashY);
+        this._dash.actor.set_size(displayGridColumnWidth, screenHeight - dashY);
+        this._dash.searchArea.height = this._workspacesY - dashY;
+        this._dash.sectionArea.height = this._workspacesHeight;
+
+        // place the 'Add Workspace' button in the bottom row of the grid
+        this._addButtonSize = Math.floor(displayGridRowHeight * 3/5);
+        this._addButtonX = this._workspacesX + this._workspacesWidth - this._addButtonSize;
+        this._addButtonY = screenHeight - Math.floor(displayGridRowHeight * 4/5);
 
         this._backOver.set_position(0, Panel.PANEL_HEIGHT);
         this._backOver.set_size(global.screen_width, contentHeight);
@@ -165,10 +189,12 @@ Overview.prototype = {
         this._transparentBackground.set_position(this._paneContainer.x, this._paneContainer.y);
         this._transparentBackground.set_size(global.screen_width - this._paneContainer.x,
                                              this._paneContainer.height);
+
+        if (this._activeDisplayPane != null)
+            this._activeDisplayPane.actor.width = displayGridColumnWidth * 2;
     },
 
     addPane: function (pane) {
-        pane.actor.width = displayGridColumnWidth * 2;
         this._paneContainer.append(pane.actor, Big.BoxPackFlags.NONE);
         // When a pane is displayed, we raise the transparent background to the top
         // and connect to button-release-event on it, then raise the pane above that.
@@ -177,6 +203,7 @@ Overview.prototype = {
         let backgroundEventId = null;
         pane.connect('open-state-changed', Lang.bind(this, function (pane, isOpen) {
             if (isOpen) {
+                pane.actor.width = displayGridColumnWidth * 2;
                 this._activeDisplayPane = pane;
                 this._transparentBackground.raise_top();
                 this._paneContainer.raise_top();
@@ -251,28 +278,13 @@ Overview.prototype = {
         this.animationInProgress = true;
 
         let global = Shell.Global.get();
-        let screenWidth = global.screen_width;
-        let screenHeight = global.screen_height; 
 
         this._dash.show();
 
-        let columnsUsed = wideScreen ? COLUMNS_FOR_WORKSPACES_WIDE_SCREEN : COLUMNS_FOR_WORKSPACES_REGULAR_SCREEN;
-        let rowsUsed = wideScreen ? ROWS_FOR_WORKSPACES_WIDE_SCREEN : ROWS_FOR_WORKSPACES_REGULAR_SCREEN;  
-         
-        let workspacesWidth = displayGridColumnWidth * columnsUsed - WORKSPACE_GRID_PADDING * 2;
-        // We scale the vertical padding by (screenHeight / screenWidth) so that the workspace preserves its aspect ratio.
-        let workspacesHeight = displayGridRowHeight * rowsUsed - WORKSPACE_GRID_PADDING * (screenHeight / screenWidth) * 2;
-
-        let workspacesX = displayGridColumnWidth + WORKSPACE_GRID_PADDING;
-        let workspacesY = displayGridRowHeight + WORKSPACE_GRID_PADDING * (screenHeight / screenWidth);
-
-        // place the 'Add Workspace' button in the bottom row of the grid
-        let addButtonSize = Math.floor(displayGridRowHeight * 3/5);
-        let addButtonX = workspacesX + workspacesWidth - addButtonSize;
-        let addButtonY = screenHeight - Math.floor(displayGridRowHeight * 4/5);
-
-        this._workspaces = new Workspaces.Workspaces(workspacesWidth, workspacesHeight, workspacesX, workspacesY, 
-                                                     addButtonSize, addButtonX, addButtonY);
+        /* TODO: make this stuff dynamic */
+        this._workspaces = new Workspaces.Workspaces(this._workspacesWidth, this._workspacesHeight,
+                                                     this._workspacesX, this._workspacesY,
+                                                     this._addButtonSize, this._addButtonX, this._addButtonY);
         this._group.add_actor(this._workspaces.actor);
 
         // The workspaces actor is as big as the screen, so we have to raise the dash above it
index fa9d6d047f737bb0da17537b091c30c30f5dd07a..c919ada851d721c0bdf588a3dedc97ec7a795bfc 100644 (file)
@@ -20,8 +20,11 @@ const DEFAULT_PADDING = 4;
 
 const PANEL_ICON_SIZE = 24;
 
-const PANEL_BACKGROUND_COLOR = new Clutter.Color();
-PANEL_BACKGROUND_COLOR.from_pixel(0x000000ff);
+const BACKGROUND_TOP = new Clutter.Color();
+BACKGROUND_TOP.from_pixel(0x414141ff);
+const BACKGROUND_BOTTOM = new Clutter.Color();
+BACKGROUND_BOTTOM.from_pixel(0x000000ff);
+
 const PANEL_FOREGROUND_COLOR = new Clutter.Color();
 PANEL_FOREGROUND_COLOR.from_pixel(0xffffffff);
 const SN_BACKGROUND_COLOR = new Clutter.Color();
@@ -83,8 +86,7 @@ AppPanelMenu.prototype = {
         this.actor.append(labelBox, Big.BoxPackFlags.NONE);
 
         this._startupBox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
-                                         y_align: Big.BoxAlignment.CENTER
-                                          });
+                                         y_align: Big.BoxAlignment.CENTER });
         this.actor.append(this._startupBox, Big.BoxPackFlags.NONE);
 
         Main.overview.connect('hiding', Lang.bind(this, function () {
@@ -161,9 +163,17 @@ Panel.prototype = {
     _init : function() {
         let global = Shell.Global.get();
 
-        this.actor = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
-                                   background_color: PANEL_BACKGROUND_COLOR
+
+        this.actor = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL
                                  });
+        let backgroundGradient = Shell.create_vertical_gradient(BACKGROUND_TOP,
+                                                                BACKGROUND_BOTTOM);
+        this.actor.connect('notify::allocation', Lang.bind(this, function () {
+            let [width, height] = this.actor.get_size();
+            backgroundGradient.set_size(width, height);
+        }));
+        this.actor.add_actor(backgroundGradient);
+
         this._leftBox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
                                       y_align: Big.BoxAlignment.CENTER,
                                       spacing: DEFAULT_PADDING,
index e1c6aba520b5646c832314c586156e4edb20032b..0618518c28699d3e70967395d11a8a027ac73d92 100644 (file)
@@ -398,7 +398,9 @@ Workspace.prototype = {
 
     // Mark the workspace selected/not-selected
     setSelected : function(selected) {
-        if (selected) {
+        let global = Shell.Global.get();
+        // Don't draw a frame if we only have one workspace
+        if (selected && global.screen.n_workspaces > 1) {
             if (this._frame)
                 return;
 
@@ -1112,6 +1114,11 @@ Workspaces.prototype = {
 
             // FIXME: deal with windows on the lost workspaces
         }
+
+        // Reset the selection state; if we went from > 1 workspace to 1,
+        // this has the side effect of removing the frame border
+        let activeIndex = global.screen.get_active_workspace_index();
+        this._workspaces[activeIndex].setSelected(true);
     },
 
     _activeWorkspaceChanged : function(wm, from, to, direction) {